<template>
  <div v-html="layoutTemplate" :style="globalStyles"></div>
</template>

<script setup lang="ts">


import { ref, onMounted, nextTick, onUnmounted, defineAsyncComponent } from 'vue';
import schema from '../json/schema-v2.json';
import { createApp } from 'vue';
import VxeUI from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'
import VxeUITable from 'vxe-table';
import ArcoVue from '@arco-design/web-vue';
import VxeUIPluginExportXLSX from '@vxe-ui/plugin-export-xlsx'
import ExcelJS from 'exceljs'
import ArcoVueIcon from '@arco-design/web-vue/es/icon';
import { ComponentService } from '../service/ComponentService';

const componentService = new ComponentService();

window.ExcelJS = ExcelJS
VxeUI.use(VxeUIPluginExportXLSX)

const layoutTemplate = ref('');
const globalStyles = ref({});
const componentInstances = new Map();
const BaseChart = defineAsyncComponent(() => import('./parts/BaseChart.vue'));
const BasePieChart = defineAsyncComponent(() => import('./parts/BasePieChart.vue'));
const BaseTable = defineAsyncComponent(() => import('./parts/BaseTable.vue'));

// 将 JSON 中的样式对象转换为 CSS 字符串
const generateStyles = () => {
  const styleSheet = document.createElement('style');
  let cssString = '';

  Object.entries(schema.layout.styles).forEach(([selector, styles]) => {
    cssString += `${selector} {\n`;
    Object.entries(styles as Record<string, string>).forEach(([prop, value]) => {
      // 将驼峰式属性名转换为 kebab-case
      const kebabProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
      cssString += `  ${kebabProp}: ${value};\n`;
    });
    cssString += '}\n';
  });

  styleSheet.textContent = cssString;
  document.head.appendChild(styleSheet);
};

// 创建并挂载组件
const mountComponent = (component: any, container: HTMLElement, props: any = {}) => {
  // 如果已存在实例，先卸载
  if (componentInstances.has(container.id)) {
    componentInstances.get(container.id).unmount();
  }

  const app = createApp(component, props)
  app.use(VxeUITable)  // 为每个组件实例注册 vxe-table、arco-design、export-xlsx   TODO  应该只让BaseTable注册
  app.use(ArcoVue)
  app.use(ArcoVueIcon)
  app.mount(container)

  // 保存实例引用
  componentInstances.set(container.id, app);
}

// 渲染组件
const renderComponents = async () => {
  const components = schema.components
  components.forEach(async (component) => {
    const container = document.getElementById(component.id)
    if (!container) return

    let componentInstance: any
    let componentProps: any = {}

    switch (component.type) {
      case 'chart-line':
        componentInstance = BaseChart
        componentProps = {
          title: component.config.title || 'Chart',
          data: component.config.data || {
            xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
            series: [{
              name: 'Data',
              data: [150, 230, 224, 218, 135, 147, 260]
            }]
          }
        }
        break
      case 'chart-pie':
        componentInstance = BasePieChart
        componentProps = {
          title: component.config.title || 'Chart',
          data: component.config.data || {
            series: [{
              name: 'Data',
              data: [150, 230, 224, 218, 135, 147]
            }]
          }
        }
        break
      case 'table':
        // 通过API初始化数据（表格数据/搜索表单等需要预先加载的数据）    TODO 请求拦截等处理
        /**
         * ****************************************************
         *                        初始化数据
         * ****************************************************
         */
        // 表格列数据初始化
        const columns = component.config.tableConfig.columnsConfig.config.localLoad
          ? component.config.tableConfig.columnsConfig.data : (await loadComponentData(component.config.tableConfig.columnsConfig, null)).data.data;

        const targetColumnsConfig = {
          ...component.config.tableConfig.columnsConfig,
          data: columns
        };

        componentInstance = BaseTable
        componentProps = {
          // 表格配置  不加载数据
          tableConfig: { ...component.config.tableConfig, columnsConfig: targetColumnsConfig },
          // 分页配置
          paginationConfig: component.config.paginationConfig,
          // 搜索配置
          searchConfig: component.config.searchConfig,
          // 导出配置
          exportConfig: component.config.exportConfig,
        }
        break
      default:
        return
    }

    if (componentInstance) {
      mountComponent(componentInstance, container, componentProps)
    }
  })
}

// 加载组件数据  TODO   表格初始化数据仍然放在这里
const loadComponentData = async (componentConfig: any, instance: any) => {
  try {
    const { api } = componentConfig.config;
    if (!api.localLoad) {
    // 使用封装的 ComponentService 发送请求
    const rawData = await componentService.fetchData({
      url: api.url,
      method: api.method,
      params: api.params
      });
      return rawData;
    } else {
      return componentConfig.data;
    }
  } catch (error) {
    console.error(`Failed to load data for ${componentConfig.id}:`, error);
  }
  // try {
  //   const { api } = componentConfig.config;

  //   // 使用封装的 ComponentService 发送请求
  //   const rawData = await componentService.fetchData({
  //     url: api.url,
  //     method: api.method,
  //     params: api.params
  //   });
  //   console.log(rawData);
  //   // 处理返回的数据
  //   const processedData = mapResponseData(rawData, api.responseMapping);
  //   console.log(processedData);
  //   // 更新组件数据
  //   if (instance && instance.updateData) {
  //     instance.updateData(processedData);
  //   }
  // } catch (error) {
  //   console.error(`Failed to load data for ${componentConfig.id}:`, error);
  // }
};

// 处理响应数据映射
// const mapResponseData = (rawData: any, mapping: any) => {
//   const result: Record<string, any> = {};

//   Object.entries(mapping).forEach(([key, path]) => {
//     if (typeof path === 'string') {
//       result[key] = path.split('.').reduce((obj, key) => obj?.[key], rawData);
//     } else if (Array.isArray(path)) {
//       result[key] = path.map((item: any) => ({
//         name: item.name,
//         data: item.dataKey.split('.').reduce((obj, key) => obj?.[key], rawData)
//       }));
//     } else if (typeof path === 'object') {
//       result[key] = {
//         type: path.type,
//         data: path.dataKey.split('.').reduce((obj, key) => obj?.[key], rawData).map((item: any) => ({
//           name: item[path.nameKey],
//           value: item[path.valueKey]
//         }))
//       };
//     }
//   });

//   return result;
// };

onMounted(async () => {
  // 设置布局模板
  layoutTemplate.value = schema.layout.template;

  // 生成并应用样式
  generateStyles();

  // 等待 DOM 更新完成
  await nextTick();

  // 渲染组件
  renderComponents();

  // setInterval(() => {
  //   const memory = (window.performance as any).memory;
  //   if (memory) {
  //     console.log('JS Heap Size:', Math.round(memory.usedJSHeapSize / (1024 * 1024)), 'MB');
  //   }
  // }, 5000);
});

// 组件卸载时清理
onUnmounted(() => {
  componentInstances.forEach(app => app.unmount());
  componentInstances.clear();
});
</script>
